package de.nak.notendb.action;

import java.util.List;

import com.opensymphony.xwork2.Action;

import de.nak.notendb.model.ExaminationResult;
import de.nak.notendb.model.ExaminationSubject;
import de.nak.notendb.model.Maniple;
import de.nak.notendb.model.Student;
import de.nak.notendb.service.exceptions.NoExaminationSubjectAvailableException;
import de.nak.notendb.service.exceptions.NoManipleAvailableException;
import de.nak.notendb.service.exceptions.NoStudentAvailableException;
import de.nak.notendb.service.interfaces.IExaminationResultService;
import de.nak.notendb.service.interfaces.IExaminationSubjectService;
import de.nak.notendb.service.interfaces.IManipleService;
import de.nak.notendb.service.interfaces.IStudentService;

/**
 * The Action to show the grade overview.
 * 
 * @author Christian Baumhof
 * 
 */
public class ShowGradeOverviewAction implements Action {

	/**
	 * The Service to load Maniples.
	 */
	private IManipleService manipleService;

	/**
	 * The Service to load Students.
	 */
	private IStudentService studentService;

	/**
	 * The Service to load ExaminationResults.
	 */
	private IExaminationResultService examinationResultService;

	/**
	 * The Service to load ExaminationSubjects.
	 */
	private IExaminationSubjectService examinationSubjectService;

	/**
	 * The id of the selected Maniple.
	 */
	private Long selectedManipleId;

	/**
	 * The list of Students.
	 */
	private List<Student> students;

	/**
	 * The list of Maniples
	 */
	private List<Maniple> maniples;

	/**
	 * The list of ExaminaionSubjects.
	 */
	private List<ExaminationSubject> subjects;

	/**
	 * An Array if ExaminationResults.
	 */
	private ExaminationResult[][][] results;

	/**
	 * An Array of Integers showing the number of tries to a corresponding
	 * Student and ExaminationSubject
	 */
	private Integer[][] numberTries;

	@Override
	public String execute() throws Exception {
		// load maniples
		try {
			maniples = manipleService.listManiples();
		} catch (NoManipleAvailableException exception) {
			return "DATA_NOT_FOUND";
		}
		if (selectedManipleId == null) {
			selectedManipleId = maniples.get(0).getId();
		}

		// load students
		try {
			students = studentService.listStudents(selectedManipleId);
		} catch (NoStudentAvailableException exception) {
			return "DATA_NOT_FOUND";
		}

		// load subjects
		try {
			subjects = examinationSubjectService
					.listExaminationSubjects(selectedManipleId);
		} catch (NoExaminationSubjectAvailableException exception) {
			return "DATA_NOT_FOUND";
		}

		// load results and initialize numberTries
		results = new ExaminationResult[subjects.size()][students.size()][3];
		numberTries = new Integer[subjects.size()][students.size()];
		List<ExaminationResult> resultList;

		for (int nrStudent = 0; nrStudent < students.size(); nrStudent++) {
			for (int nrSubject = 0; nrSubject < subjects.size(); nrSubject++) {
				Long studentId = students.get(nrStudent).getId();
				Long subjectId = subjects.get(nrSubject).getId();
				resultList = examinationResultService
						.listAllValidExaminationResultsOfAStudentAndASubject(
								studentId, subjectId);
				for (int nrTry = 0; nrTry < resultList.size(); nrTry++) {
					results[nrSubject][nrStudent][nrTry] = resultList
							.get(nrTry);
				}
				numberTries[nrSubject][nrStudent] = resultList.size();
			}
		}

		return SUCCESS;
	}

	/**
	 * Returns the id of the selected Maniple.
	 * 
	 * @return the id of the selected Maniple.
	 */
	public Long getSelectedManipleId() {
		return selectedManipleId;
	}

	/**
	 * Setter for the id of the selected Maniple.
	 * 
	 * @param Long
	 *            selectedManipleI.d
	 */
	public void setSelectedManipleId(Long selectedManipleId) {
		this.selectedManipleId = selectedManipleId;
	}

	/**
	 * Return the list of Students.
	 * 
	 * @return the list of Students.
	 */
	public List<Student> getStudents() {
		return students;
	}

	/**
	 * Return the list of Maniples.
	 * 
	 * @return the list of Maniples.
	 */
	public List<Maniple> getManiples() {
		return maniples;
	}

	/**
	 * Return the list of ExaminationSubjects.
	 * 
	 * @return the list of ExaminationSubjects.
	 */
	public List<ExaminationSubject> getSubjects() {
		return subjects;
	}

	/**
	 * Setter for the ManipleService.
	 * 
	 * @param IManipleService
	 *            manipleService.
	 */
	public void setManipleService(IManipleService manipleService) {
		this.manipleService = manipleService;
	}

	/**
	 * Setter for the StudentService.
	 * 
	 * @param IStudentService
	 *            studentService.
	 */
	public void setStudentService(IStudentService studentService) {
		this.studentService = studentService;
	}

	/**
	 * Setter for the ExaminationSubjectService.
	 * 
	 * @param IExaminationSubjectService
	 *            examinationSubjectService.
	 */
	public void setExaminationSubjectService(
			IExaminationSubjectService examinationSubjectService) {
		this.examinationSubjectService = examinationSubjectService;
	}

	/**
	 * Setter for the ExaminationResultService.
	 * 
	 * @param IExaminationResultService
	 *            examinationResultService
	 */
	public void setExaminationResultService(
			IExaminationResultService examinationResultService) {
		this.examinationResultService = examinationResultService;
	}

	/**
	 * Returns the Array of ExaminationResults.
	 * 
	 * @return the Array of ExaminationResults.
	 */
	public ExaminationResult[][][] getResults() {
		return results;
	}

	/**
	 * Returns the Array of Integers (number of tries).
	 * 
	 * @return the Array of Integers (number of tries).
	 */
	public Integer[][] getNumberTries() {
		return numberTries;
	}

}
